package savi.classes;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.jdo.*;

import savi.classes.Datastore;
import savi.jdo.*;

public class Events {
	private static Accounts accounts = Accounts.inst();
	private static Events instance = null;

	private PersistenceManager getPM() {
		return Datastore.getPersistanceManager();
	}

	public static Events inst() {
		if (instance == null)
			instance = new Events();
		return instance;
	}

	private int getNewEventID() {
		PersistenceManager pm = null;
		int result;

		String query = "SELECT FROM " + Event.class.getName();

		try {
			pm = getPM();

			@SuppressWarnings("unchecked")
			List<Event> events = (List<Event>) pm.newQuery(query).execute();

			if (events.isEmpty())
				result = 0;
			else
				result = Integer.parseInt(events.get(events.size() - 1)
						.getEventID().replace("c", "")) + 1;
		} finally {
			if (pm != null)
				pm.close();
		}

		return result;
	}

	private int getNewEventSerialNo() {
		PersistenceManager pm = null;
		int result;

		String query = "SELECT FROM " + StudentEvent.class.getName();

		try {
			pm = getPM();

			@SuppressWarnings("unchecked")
			List<StudentEvent> events = (List<StudentEvent>) pm.newQuery(query)
					.execute();

			if (events.isEmpty())
				result = 0;
			else
				result = Integer.parseInt(events.get(events.size() - 1)
						.getSerialNo().replace("c", "")) + 1;
		} finally {
			if (pm != null)
				pm.close();
		}

		return result;
	}

	public void addEvent(String moduleID, String type, String location,
			Date startTime, Date endTime, String description) {
		PersistenceManager pm = null;
		int eventID = getNewEventID();

		Event event = new Event("c"+eventID, accounts.getUserName(),
				moduleID, type, location, startTime, endTime, description);
		try {
			pm = getPM();
			pm.makePersistent(event);
		} finally {
			if (pm != null)
				pm.close();
		}
		joinEvent("c"+eventID);
	}

	public void deleteEvent(int eventID) {
		PersistenceManager pm = null;

		String query1 = "SELECT FROM " + Event.class.getName()
				+ " WHERE eventID == '" + eventID + "'";
		String query2 = "SELECT FROM " + StudentEvent.class.getName()
				+ " WHERE eventID == '" + eventID + "'";

		try {
			pm = getPM();

			@SuppressWarnings("unchecked")
			List<Event> events = (List<Event>) pm.newQuery(query1).execute();

			@SuppressWarnings("unchecked")
			List<StudentEvent> studentEvents = (List<StudentEvent>) pm
					.newQuery(query2).execute();

			for (int i = 0; i < events.size(); i++)
				pm.deletePersistent(events.get(i));
			for (int j = 0; j < studentEvents.size(); j++)
				pm.deletePersistent(studentEvents.get(j));
		} finally {
			if (pm != null)
				pm.close();
		}
	}

	public void updateEvent(int eventID, String ownerId, String moduleID,
			String type, String location, Date startTime, Date endTime,
			String description) {
		PersistenceManager pm = null;
		String query = "SELECT * FROM " + Event.class.getName()
				+ " WHERE eventID == '" + eventID + "'";

		try {
			pm = getPM();

			@SuppressWarnings("unchecked")
			List<Event> event = (List<Event>) pm.newQuery(query).execute();

			if (ownerId != null)
				event.get(0).setOwnerID(ownerId);
			if (moduleID != null)
				event.get(0).setModuleID(moduleID);
			if (type != null)
				event.get(0).setType(type);
			if (location != null)
				event.get(0).setLocation(location);
			if (startTime != null)
				event.get(0).setStartTime(startTime);
			if (endTime != null)
				event.get(0).setEndTime(endTime);
			if (description != null)
				event.get(0).setDescription(description);
		} finally {
			if (pm != null)
				pm.close();
		}
	}

	public void joinEvent(String eventID) {
		PersistenceManager pm = null;
		StudentEvent studentEvent = new StudentEvent(accounts.getUserName(),
				eventID, "c" + this.getNewEventSerialNo());

		try {
			pm = getPM();
			pm.makePersistent(studentEvent);
		} finally {
			if (pm != null)
				pm.close();
		}
	}

	public void leaveEvent(int eventID) {
		PersistenceManager pm = null;

		String query = "SELECT FROM " + StudentEvent.class.getName()
				+ " WHERE googleID == '" + accounts.getUserName()
				+ "' AND eventID == '" + eventID + "'";

		try {
			pm = getPM();

			@SuppressWarnings("unchecked")
			List<StudentEvent> studentEvents = (List<StudentEvent>) pm
					.newQuery(query).execute();

			pm.deletePersistent(studentEvents.get(0));
		} finally {
			if (pm != null)
				pm.close();
		}
	}

	public String getEventDesc(int eventID) {
		PersistenceManager pm = null;
		String result = "";

		String query1 = "SELECT FROM " + Event.class.getName()
				+ " WHERE eventID == '" + eventID + "'";
		String query2 = "SELECT FROM " + StudentEvent.class.getName()
				+ " WHERE eventID=='" + eventID + "' AND googleID=='"
				+ accounts.getUserName() + "'";

		try {
			pm = getPM();

			@SuppressWarnings("unchecked")
			Event event = ((List<Event>) pm.newQuery(query1).execute()).get(0);
			@SuppressWarnings("unchecked")
			List<StudentEvent> studentEvent = (List<StudentEvent>) pm.newQuery(
					query2).execute();
			result = "<EVENTCHILD>";
			result += "<EVENTID>" + event.getEventID() + "</EVENTID>";
			result += "<MODULE>" + event.getModuleID() + "</MODULE>";
			result += "<TYPE>" + event.getType() + "</TYPE>";
			result += "<LOCATION>" + event.getLocation() + "</LOCATION>";
			result += "<OWNER>" + event.getOwnerID() + "</OWNER>";
			result += "<STARTTIME>" + event.getStartTime() + "</STARTTIME>";
			result += "<ENDTIME>" + event.getEndTime() + "</ENDTIME>";
			result += "<DESCRIPTION>" + event.getDescription()
					+ "</DESCRIPTION>";
			result += this.getUsersOfEvent(event.getEventID());
			if (studentEvent.size() > 0)
				result += "<JOINED>" + Boolean.toString(true) + "</JOINED>";
			else
				result += "<JOINED>" + Boolean.toString(false) + "</JOINED>";
			result += "</EVENTCHILD>";
		} finally {
			if (pm != null)
				pm.close();
		}

		return result;
	}

	public String getEventToXML(Event event) {
		String result = "";

		result = "<EVENTCHILD>";
		result += "<EVENTID>" + event.getEventID() + "</EVENTID>";
		result += "<MODULE>" + event.getModuleID() + "</MODULE>";
		result += "<TYPE>" + event.getType() + "</TYPE>";
		result += "<STARTTIME>" + event.getStartTime() + "</STARTTIME>";
		result += "</EVENTCHILD>";

		return result;
	}

	public String getEventsToXML(List<Event> events) {
		String result = "<EVENTS>";

		for (Event event : events) {
			result += getEventToXML(event);
		}

		result += "</EVENTS>";

		return result;
	}

	private String getUsersOfEvent(String eventID) {
		PersistenceManager pm = null;
		String xmlResult = "";

		String query = "SELECT googleID FROM " + StudentEvent.class.getName()
				+ " WHERE eventID =='" + eventID + "'";

		try {
			pm = getPM();

			@SuppressWarnings("unchecked")
			List<String> googleIDs = (List<String>) pm.newQuery(query)
					.execute();

			xmlResult = "<STUDENTS>";
			for (String googleID : googleIDs) {
				xmlResult += "<STUDENTID>" + googleID + "</STUDENTID>";
			}
			xmlResult = "</STUDENTS>";

		} finally {
			if (pm != null)
				pm.close();
		}

		return xmlResult;
	}

	private List<Event> getEventsByModuleCode(String moduleID) {
		PersistenceManager pm = null;
		List<Event> events = new ArrayList<Event>();
		String query = "SELECT FROM " + Event.class.getName()
				+ " WHERE moduleID == '" + moduleID + "'";

		try {
			pm = getPM();

			@SuppressWarnings("unchecked")
			List<Event> newEvents = (List<Event>) pm.newQuery(query).execute();

			events = newEvents;
		} finally {
			if (pm != null)
				pm.close();
		}

		return events;
	}

	public String getFutureEventSuggestionsForStudent() {
		PersistenceManager pm = null;
		Date today = new Date();
		String xmlResult = "";

		String query1 = "SELECT FROM " + StudentModule.class.getName()
				+ " WHERE googleID == '" + accounts.getUserName() + "'";
		String query2 = "SELECT FROM " + StudentEvent.class.getName()
				+ " WHERE googleID=='" + accounts.getUserName() + "'";
		String query3 = "SELECT FROM " + Event.class.getName();
				//+ " WHERE endTime >= " + today ;

		try {
			pm = getPM();

			@SuppressWarnings("unchecked")
			List<StudentModule> studentModules = (List<StudentModule>) pm
					.newQuery(query1).execute();

			@SuppressWarnings("unchecked")
			List<StudentEvent> studentEvents = (List<StudentEvent>) pm
					.newQuery(query2).execute();

			@SuppressWarnings("unchecked")
			List<Event> events = (List<Event>) pm.newQuery(query3).execute();

			List<String> eventIDs = new ArrayList<String>();
			for (int i = 0; i < studentEvents.size(); i++) {
				eventIDs.add(events.get(i).getEventID());
			}

			List<String> modules = new ArrayList<String>();
			for (int i = 0; i < studentModules.size(); i++) {
				modules.add(studentModules.get(i).getmoduleID());
			}

			List<Event> finalEvents = new ArrayList<Event>();
			for (int i = 0; i < events.size(); i++) {
				if (modules.contains(events.get(i).getModuleID())
						|| (!eventIDs.contains(events.get(i).getEventID())))
					finalEvents.add(events.get(i));
			}

			xmlResult = getEventsToXML(finalEvents);
		} finally {
			if (pm != null)
				pm.close();
		}
		return xmlResult;
	}

	public String getFutureEventsJoinedByStudent() {
		PersistenceManager pm = null;
		Date today = new Date();
		String xmlResult = "";
		String query1 = "SELECT * FROM " + StudentModule.class.getName()
				+ " WHERE googleID == '" + accounts.getUserName() + "'";
		String query2 = "SELECT * FROM " + StudentEvent.class.getName()
				+ " WHERE googleID=='" + accounts.getUserName() + "'";
		String query3 = "SELECT * FROM " + Event.class.getName()
				+ " WHERE endTime >= " + today + " ORDER BY startTime";

		try {
			pm = getPM();

			@SuppressWarnings("unchecked")
			List<StudentModule> studentModules = (List<StudentModule>) pm
					.newQuery(query1).execute();

			@SuppressWarnings("unchecked")
			List<StudentEvent> studentEvents = (List<StudentEvent>) pm
					.newQuery(query2).execute();

			@SuppressWarnings("unchecked")
			List<Event> events = (List<Event>) pm.newQuery(query3).execute();

			List<String> eventIDs = new ArrayList<String>();
			for (int i = 0; i < studentEvents.size(); i++) {
				eventIDs.add(events.get(i).getEventID());
			}

			List<String> modules = new ArrayList<String>();
			for (int i = 0; i < studentModules.size(); i++) {
				modules.add(studentModules.get(i).getmoduleID());
			}

			List<Event> finalEvents = new ArrayList<Event>();
			for (int i = 0; i < events.size(); i++) {
				if (modules.contains(events.get(i).getModuleID())
						|| eventIDs.contains(events.get(i).getEventID()))
					finalEvents.add(events.get(i));
			}

			xmlResult = getEventsToXML(finalEvents);
		} finally {
			if (pm != null)
				pm.close();
		}

		return xmlResult;
	}

	public String getPastEventsOfStudentModules() {
		PersistenceManager pm = null;
		Date today = new Date();
		String xmlResult = "";

		String query1 = "SELECT FROM " + StudentModule.class.getName()
				+ " WHERE googleID == '" + accounts.getUserName() + "'";
		String query2 = "SELECT FROM " + Event.class.getName()
				+ " WHERE endTime <= " + today + " ORDER BY startTime";

		try {
			pm = getPM();

			@SuppressWarnings("unchecked")
			List<StudentModule> studentModules = (List<StudentModule>) pm
					.newQuery(query1).execute();
			@SuppressWarnings("unchecked")
			List<Event> events = (List<Event>) pm.newQuery(query2).execute();

			List<String> modules = new ArrayList<String>();
			for (int i = 0; i < studentModules.size(); i++) {
				modules.add(studentModules.get(i).getmoduleID());
			}

			List<Event> finalEvents = new ArrayList<Event>();
			for (int i = 0; i < events.size(); i++) {
				if (modules.contains(events.get(i).getModuleID()))
					finalEvents.add(events.get(i));
			}

			xmlResult = getEventsToXML(finalEvents);
		} finally {
			if (pm != null)
				pm.close();
		}

		return xmlResult;
	}

	public String getAllUserModuleEvents() {
		PersistenceManager pm = null;
		String xmlResult = "";

		String query = "SELECT moduleID FROM " + Student.class.getName()
				+ " WHERE googleID == '" + accounts.getUserName() + "'";

		try {
			pm = getPM();

			@SuppressWarnings("unchecked")
			List<String> studentModules = (List<String>) pm.newQuery(query)
					.execute();

			xmlResult = "<MODULES>";
			for (String module : studentModules) {
				xmlResult += "<>";
				xmlResult += getEventsToXML(getEventsByModuleCode(module));
				xmlResult += "</MODULECHILD>";
			}
			xmlResult += "</MODULES>";

		} finally {
			if (pm != null)
				pm.close();
		}

		return xmlResult;
	}

	public String getAllUserCreatedEvents() {
		PersistenceManager pm = null;
		String xmlResult = "";
		String query = "SELECT FROM " + Event.class.getName()
				+ " WHERE ownerID=='" + accounts.getUserName() + "'";
		try{
			pm = getPM();
			@SuppressWarnings("unchecked")
			List<Event> events = (List<Event>) pm.newQuery(query).execute();
			xmlResult = getEventsToXML(events);
		}
		finally {
			if(pm!=null)
				pm.close();
		}
		return xmlResult;
	}
}
